<?php

namespace App\Http\Controllers;

use DB;
use Illuminate\Http\Request;
use Validator;

use Ptime3\Functions\JoinData;
use Ptime3\Functions\Queue;

class CommentController extends Controller
{
    private function indexInner($input){
        $appId      = $input["app_id"];
        $object     = $input["object"];
        $objectId   = $input["object_id"];
        $orderField = (isset($input["order"]) && $input["order"] == "hot")?"star_count":"created_at";
        $minStarCount = (isset($input["order"]) && $input["order"] == "hot")?3:0;
        $skip       = empty($input["page"])?0:20*($input["page"]-1);

        $commentResult = DB::table("cm_comment")
          ->select("cm_comment.id","cm_comment.content","cm_object.star_count","cm_comment.created_at","cm_comment.is_deleted","cm_comment.user_id","cm_comment.replied_user_id",
               "cm_star.created_at AS stared_at"
               )
          ->leftJoin('cm_star', function ($join) use ($input,$object) {
                $join->on('cm_star.object_id', '=', 'cm_comment.id')
                    ->where('cm_star.app_id', '=', $input["app_id"])
                    ->where('cm_star.object', '=', $object)
                    ->where('cm_star.user_id', '=', empty($input["user_id"])?0:$input["user_id"]);
          })
          ->leftJoin('cm_object', function ($join) use ($input,$minStarCount,$object) {
                $join->on('cm_object.object_id', '=', 'cm_comment.id')
                    ->where('cm_object.app_id', '=', $input["app_id"])
                    ->where('cm_object.object', '=', $object)
                    ->where("cm_object.star_count",">=",$minStarCount);
          })
          ->where("cm_comment.app_id",$appId)
          ->where("cm_comment.object",$object)
          ->where("cm_comment.object_id",$objectId)
          ->orderBy($orderField,"DESC")
          ->skip($skip)->take(20)
          ->get();

        foreach ($commentResult as $value) {
            $value->is_stared  = $value->stared_at == null ? 0 : 1;
            $value->star_count = $value->star_count == null ? 0 : $value->star_count;
            $value->is_owned   = (!empty($input["user_id"]) && $value->user_id == $input["user_id"]) ? 1 : 0;
            unset($value->stared_at);
        }
        $commentResult = JoinData::user($commentResult);
        $commentResult = JoinData::user($commentResult,"replied_user");

        return $commentResult;
    }

     /**
     * @api {get} /comment GetCommentList
     * @apiVersion 0.2.0
     * @apiName GetCommentList
     * @apiGroup comment
     * @apiPermission app
     *
     * @apiDescription 获取评论列表
     *
     * @apiParam {Number} app_id *应用id.
     * @apiParam {String} object *实体名称.
     * @apiParam {Number} object_id *实体id.
     * @apiParam {Number} order 排序 new/hot.
     * @apiParam {Number} page 页码.
     * @apiParam {Number} user_id 用户id.
     *
     * @apiSuccess {Boolean} error 是否错误.
     * @apiSuccess {Object[]} result 评论数据.
     * @apiSuccess {String} result.content 评论内容.
     * @apiSuccess {Number} result.star_count 赞数.
     * @apiSuccess {Datetime} result.created_at 创建时间.
     * @apiSuccess {String} result.user_name 用户姓名.
     * @apiSuccess {String} result.user_icon 用户头像.
     * @apiSuccess {String} result.replied_user_name 被回复者姓名.
     * @apiSuccess {String} message 提示消息
     *
     * @apiError statusError 状态错误.
     * @apiSampleRequest http://dev.timepicker.cn/api/comment
     */
    function index(Request $request){
        $input = $request->all();
        //参数检验
        $validator = Validator::make($input,
            [
                'app_id'      => 'required|integer|min:1',
                'object'      => 'required|string|min:2',
                'object_id'   => 'required|string|min:1',
                'order'       => 'string|min:1',
                'page'        => 'integer|min:1',
                'user_id'     => 'integer'
            ]
        );
        if($validator->fails())
            return $this::jsonResponse(true,$validator->messages(),"paramError");
        
        $commentResult = $this->indexInner($input);
        return $this::jsonResponse(false,$commentResult);
    }


     /**
     * @api {get} /comment/{id} GetCommentDetail
     * @apiVersion 0.2.0
     * @apiName GetCommentDetail
     * @apiGroup comment
     * @apiPermission app
     *
     * @apiParam {Number} user_id 用户id.
     *
     * @apiDescription 获取评论详情
     *
     * @apiSuccess {Boolean} error 是否错误.
     * @apiSuccess {Object[]} result 评论数据.
     * @apiSuccess {String} result.content 评论内容.
     * @apiSuccess {Number} result.star_count 赞数.
     * @apiSuccess {Datetime} result.created_at 创建时间.
     * @apiSuccess {String} result.user_name 用户姓名.
     * @apiSuccess {String} result.user_icon 用户头像.
     * @apiSuccess {String} result.replied_user_name 被回复者姓名.
     * @apiSuccess {String} message 提示消息
     *
     * @apiError statusError 状态错误.
     * @apiSampleRequest http://dev.timepicker.cn/api/comment/1
     */
    function show(Request $request, $id){
        $input = $request->all();
        //参数检验
        $validator = Validator::make($input,
            [
                'user_id'     => 'integer'
            ]
        );
        if($validator->fails()){
            return $this::jsonResponse(true,$validator->messages(),"paramError");
        }

        $appId = DB::table("cm_comment")->where("id",$id)->value("app_id");
        $commentResult = DB::table("cm_comment")
          ->select("cm_comment.id","cm_comment.content","cm_object.star_count","cm_comment.created_at","cm_comment.is_deleted","cm_comment.user_id","cm_comment.replied_user_id",
               "cm_star.created_at AS stared_at"
               )
          ->leftJoin('cm_star', function ($join) use ($input) {
                $join->on('cm_star.object_id', '=', 'cm_comment.id')
                    ->where('cm_star.app_id', '=', 'cm_comment.app_id')
                    ->where('cm_star.object', '=', "comment")
                    ->where('cm_star.user_id', '=', empty($input["user_id"])?0:$input["user_id"]);
          })
          ->leftJoin('cm_object', function ($join) use ($appId) {
                $join->on('cm_object.object_id', '=', 'cm_comment.id')
                    ->where('cm_object.app_id', '=', $appId)
                    ->where('cm_object.object', '=', "comment");
          })
          ->where("cm_comment.id",$id)
          ->first();

        if(empty($commentResult))
            return $this::jsonResponse(true,"","inputError");
        
        $commentResult->is_stared  = $commentResult->stared_at == null ? 0 : 1;
        $commentResult->star_count = $commentResult->star_count == null ? 0 : $commentResult->star_count;
        $commentResult->is_owned   = (!empty($input["user_id"]) && $commentResult->user_id == $input["user_id"]) ? 1 : 0;
        unset($commentResult->stared_at);

        $commentResult = JoinData::user([$commentResult])[0];
        $commentResult = JoinData::user([$commentResult],"replied_user")[0];

        return $this::jsonResponse(false,$commentResult);
    }

    /**
     * @api {post} /comment CreateComment
     * @apiVersion 0.2.0
     * @apiName CreateComment
     * @apiGroup comment
     * @apiPermission app
     *
     * @apiDescription 创建评论
     *
     * @apiParam {Number} app_id *应用id.
     * @apiParam {String} object *实体名称.
     * @apiParam {Number} object_id *实体id.
     * @apiParam {Number} user_id *用户id.
     * @apiParam {Number} replied_comment_id 被回复评论id.
     * @apiParam {String} content *内容.
     *
     * @apiSuccess {Boolean} error 是否错误.
     * @apiSuccess {Number} result 新建评论id.
     * @apiSuccess {String} message 提示消息.
     *
     * @apiError paramError 参数错误.
     * @apiSampleRequest http://192.168.1.120:82/api/comment
     */
     public function store(Request $request){
        $input = $request->all();
        //参数检验
        $validator = Validator::make($input,
            [
                'app_id'      => 'required|integer|min:1',
                'object'      => 'required|string|min:2',
                'object_id'   => 'required|string|min:1',
                'user_id'     => 'required|integer|min:1',
                'content'     => 'required|string|min:2',
                'replied_comment_id' => 'integer|min:1',
            ]
        );
        if($validator->fails()){
            return $this::jsonResponse(true,$validator->messages(),"paramError");
        }

        if(!empty($input["replied_comment_id"]))
          $input["replied_user_id"] = DB::table("cm_comment")->where("id",$input["replied_comment_id"])->value("user_id");

        $commentData = [
            "app_id" => $input["app_id"],
            "object" => $input["object"],
            "object_id" => $input["object_id"],
            "user_id" => $input["user_id"],
            "content" => $input["content"],
            "replied_comment_id" => empty($input["replied_comment_id"])?0:$input["replied_comment_id"],
            "replied_user_id"    => empty($input["replied_user_id"])?0:$input["replied_user_id"]
        ];

        $calendarId = DB::table("cm_comment")->insertGetId($commentData);

        $incrementResult = DB::table("cm_object")
          ->where("app_id",$input["app_id"])
          ->where("object",$input["object"])
          ->where("object_id",$input["object_id"])
          ->increment("comment_count");
        
        if(!$incrementResult){
          $objectData = [
            "app_id" => $input["app_id"],
            "object" => $input["object"],
            "object_id" => $input["object_id"],
            "comment_count" => 1
          ];
          DB::table("cm_object")->insert($objectData);
        }

        $commentData["user_name"] = "{{user:id:$input[user_id]:name}}";
        if(!empty($input["replied_comment_id"]))
            $commentData["replied_comment_content"] = DB::table("cm_comment")->where("id",$input["replied_comment_id"])->value("content");
        else
            $commentData["replied_comment_content"] = "";
        $eventHookData = [
            "app_id"=>$input["app_id"],
            "event" =>"commentStore",
            "data"  =>$commentData
        ];
        Queue::put("appevent",$eventHookData);

        return $this->jsonResponse(false,$calendarId);
     }

    /**
     * @api {delete} /comment/{id} DeleteComment
     * @apiVersion 0.2.0
     * @apiName DeleteComment
     * @apiGroup comment
     * @apiPermission app
     *
     * @apiDescription 删除评论
     *
     * @apiSuccess {Boolean} error 是否错误.
     * @apiSuccess {Boolean} result 结果.
     * @apiSuccess {String} message 提示消息.
     *
     * @apiError paramError 参数错误.
     * @apiSampleRequest http://192.168.1.120:82/api/comment/1
     */
     public function destroy($commentId){
        
        $result = DB::table("cm_comment")->where("id",$commentId)->update(["is_deleted"=>true]);
        $commentResult = DB::table("cm_comment")->select("app_id","object","object_id")->where("id",$commentId)->first();
        if(!empty($commentResult))
             DB::table("cm_object")
               ->where("app_id",$commentResult->app_id)
               ->where("object",$commentResult->object)
               ->where("object_id",$commentResult->object_id)
               ->decrement("comment_count");
        return $this->jsonResponse(false,$result);
     }

     /**
     * @api {get} /comment/{id}/relate GetCommentRelate
     * @apiVersion 0.2.0
     * @apiName GetCommentRelate
     * @apiGroup comment
     * @apiPermission app
     *
     * @apiDescription 评论相关会话
     *
     * @apiParam {Number} page *页码.
     * @apiParam {Number} user_id 当前用户id.
     *
     * @apiSuccess {Boolean} error 是否错误.
     * @apiSuccess {Object[]} result 应用数据.
     * @apiSuccess {String} result.content 评论内容.
     * @apiSuccess {Number} result.star_count 赞数.
     * @apiSuccess {Datetime} result.created_at 创建时间.
     * @apiSuccess {String} result.user_name 用户姓名.
     * @apiSuccess {String} result.user_icon 用户头像.
     * @apiSuccess {String} result.replied_user_name 被回复者姓名.
     * @apiSuccess {String} message 提示消息.
     *
     * @apiError statusError 状态错误.
     * @apiSampleRequest http://dev.timepicker.cn/api/comment/1/relate
     */
     function relateIndex(Request $request, $id){
        $input   = $request->all();
        $skip    = empty($input["page"])?0:20*($input["page"]-1);

        $commentResult = DB::table("cm_comment")->select("user_id","replied_user_id","app_id","object","object_id")->where("id",$id)->first();

        if(empty($commentResult))
            return $this::jsonResponse(true,"no this comment");

        $relateCommentResult = DB::table("cm_comment")
            ->select("cm_comment.id","cm_comment.content","cm_object.star_count","cm_comment.created_at","cm_comment.is_deleted","cm_comment.user_id","cm_comment.replied_user_id",
                "cm_star.created_at AS stared_at"
                )
            ->leftJoin('cm_star', function ($join) use ($input,$commentResult) {
                $join->on('cm_star.object_id', '=', 'cm_comment.id')
                    ->where('cm_star.app_id', '=', $commentResult->app_id)
                    ->where('cm_star.object', '=', "comment")
                    ->where('cm_star.user_id', '=', empty($input["user_id"])?0:$input["user_id"]);
            })
            ->leftJoin('cm_object', function ($join) use ($commentResult) {
                $join->on('cm_object.object_id', '=', 'cm_comment.id')
                    ->where('cm_object.app_id', '=', $commentResult->app_id)
                    ->where('cm_object.object', '=', "comment");
            })
            ->where(function ($query) use ($commentResult) {
                $query->where('cm_comment.user_id', $commentResult->user_id)
                      ->where('cm_comment.replied_user_id', 0)
                      ->where('cm_comment.app_id', $commentResult->app_id)
                      ->where('cm_comment.object', $commentResult->object)
                      ->where('cm_comment.object_id', $commentResult->object_id);
            })
            ->orWhere(function ($query) use ($commentResult) {
                $query->where('cm_comment.user_id', $commentResult->replied_user_id)
                      ->where('cm_comment.replied_user_id', 0)
                      ->where('cm_comment.app_id', $commentResult->app_id)
                      ->where('cm_comment.object', $commentResult->object)
                      ->where('cm_comment.object_id', $commentResult->object_id);
            })
            ->orWhere(function ($query) use ($commentResult) {
                $query->where('cm_comment.user_id', $commentResult->user_id)
                      ->where('cm_comment.replied_user_id', $commentResult->replied_user_id)
                      ->where('cm_comment.app_id', $commentResult->app_id)
                      ->where('cm_comment.object', $commentResult->object)
                      ->where('cm_comment.object_id', $commentResult->object_id);
            })
            ->orWhere(function ($query) use ($commentResult) {
                $query->where('cm_comment.user_id', $commentResult->replied_user_id)
                      ->where('cm_comment.replied_user_id', $commentResult->user_id)
                      ->where('cm_comment.app_id', $commentResult->app_id)
                      ->where('cm_comment.object', $commentResult->object)
                      ->where('cm_comment.object_id', $commentResult->object_id);
            })
            ->orderBy("created_at","ASC")
            ->skip($skip)->take(20)
            ->get();

        foreach ($relateCommentResult as $value) {
            $value->is_stared  = $value->stared_at == null ? 0 : 1;
            $value->star_count = $value->star_count == null ? 0 : $value->star_count;
            $value->is_owned   = (!empty($input["user_id"]) && $value->user_id == $input["user_id"]) ? 1 : 0;
            unset($value->stared_at);
        }

        $commentResult = JoinData::user($relateCommentResult);
        $commentResult = JoinData::user($relateCommentResult,"replied_user");

        return $this::jsonResponse(false,$relateCommentResult);
     }

    /**
     * @api {post} /comment/{id}/star CreateCommentStar
     * @apiVersion 0.2.0
     * @apiName CreateCommentStar
     * @apiGroup comment
     * @apiPermission app
     *
     * @apiDescription 赞评论
     *
     * @apiParam {Number} user_id *用户id.
     *
     * @apiSuccess {Boolean} error 是否错误.
     * @apiSuccess {Number} result 新建赞id.
     * @apiSuccess {String} message 提示消息.
     *
     * @apiError paramError 参数错误.
     * @apiSampleRequest http://192.168.1.120:82/api/comment/1/star
     */
    public function starStore(Request $request, $commentId){
        $input = $request->all();
        //参数检验
        $validator = Validator::make($input,
            [
                'user_id'     => 'required|integer|min:1',
            ]
        );
        if($validator->fails()){
            return $this::jsonResponse(true,$validator->messages(),"paramError");
        }

        $appId = DB::table("cm_comment")->where("id",$commentId)->value("app_id");

        $starData = [
            "app_id"   =>$appId,
            "object"   =>"comment",
            "object_id"=>$commentId,
            "user_id"  =>$input["user_id"]
        ];
        Queue::put("restapi",["post","comment","star",$starData]);
        
        return $this::jsonResponse(false,true);
    }

    /**
     * @api {delete} /comment/{id}/star DeleteCommentStar
     * @apiVersion 0.2.0
     * @apiName DeleteCommentStar
     * @apiGroup comment
     * @apiPermission app
     *
     * @apiDescription 取消赞评论
     *
     * @apiParam {Number} user_id *用户id.
     *
     * @apiSuccess {Boolean} error 是否错误.
     * @apiSuccess {Number} result 结果.
     * @apiSuccess {String} message 提示消息.
     *
     * @apiError paramError 参数错误.
     * @apiSampleRequest http://192.168.1.120:82/api/comment/1/star
     */
    public function starDestroy(Request $request, $commentId){
        $input = $request->all();
        //参数检验
        $validator = Validator::make($input,
            [
                'user_id'     => 'required|integer|min:1',
            ]
        );
        if($validator->fails()){
            return $this::jsonResponse(true,$validator->messages(),"paramError");
        }

        $appId = DB::table("cm_comment")->where("id",$commentId)->value("app_id");
        if(empty($appId))
            return $this::jsonResponse(true,[],"comment not exist");

        $starData = [
            "app_id"   =>$appId,
            "object"   =>"comment",
            "object_id"=>$commentId,
            "user_id"  =>$input["user_id"]
        ];
        Queue::put("restapi",["delete","comment","star",$starData]);

        return $this::jsonResponse(false,true);
    }


    /**
     * @api {get} /comment/count GetCommentStarCount
     * @apiVersion 0.2.0
     * @apiName GetCommentStarCount
     * @apiGroup comment
     * @apiPermission app
     *
     * @apiDescription 批量获取评论赞的数量
     *
     * @apiParam {Number} app_id *应用id.
     * @apiParam {String} object *实体名称.
     * @apiParam {Number} object_ids *实体id集，逗号隔开.
     * @apiParam {Number} user_id 用户id.
     *
     * @apiSuccess {Boolean} error 是否错误.
     * @apiSuccess {Object[]} result 数据.
     * @apiSuccess {String} result.object_id 实体id.
     * @apiSuccess {Number} result.star_count 赞数.
     * @apiSuccess {Number} result.comment_count 评论数.
     * @apiSuccess {String} message 提示消息.
     *
     * @apiError paramError 参数错误.
     * @apiSampleRequest http://dev.timepicker.cn/api/comment/count
     */
    public function countIndex(Request $request){
        $input = $request->all();
        //参数检验
        $validator = Validator::make($input,
            [
                'app_id'      => 'required|integer|min:1',
                'object'      => 'required|string|min:2',
                'object_ids'   => 'required|string|min:1',
                'user_id'     => 'integer'
            ]
        );
        if($validator->fails()){
            return $this::jsonResponse(true,$validator->messages(),"paramError");
        }

        $appId      = $input["app_id"];
        $object     = $input["object"];
        $objectIds  = explode(",", $input["object_ids"]);

        $objectResult = DB::table("cm_object")
            ->select("cm_object.object_id","cm_object.star_count","cm_object.comment_count","cm_star.created_at AS stared_at")
            ->leftJoin('cm_star', function ($join) use ($input) {
                $join->on('cm_star.object_id', '=', 'cm_object.object_id')
                    ->where('cm_star.app_id', '=', $input["app_id"])
                    ->where('cm_star.object', '=', $input["object"])
                    ->where('cm_star.user_id', '=', empty($input["user_id"])?0:$input["user_id"]);
            })
            ->where("cm_object.app_id",$appId)
            ->where("cm_object.object",$object)
            ->whereIn("cm_object.object_id",$objectIds)
            ->get();

        $objectHash = [];
        foreach ($objectResult as $value) {
            $value->is_stared = $value->stared_at == null ? 0 : 1;
            unset($value->stared_at);
            $objectHash[$value->object_id] = $value;
        }

        $objectReturn = [];
        foreach ($objectIds as $objectId) {
            $objectReturn[] = isset($objectHash[$objectId])?$objectHash[$objectId]:[
                "object_id"    =>$objectId,
                "star_count"   =>0,
                "comment_count"=>0,
                "is_stared"    =>0
            ];
        }

        return $this::jsonResponse(false,$objectReturn);
    }

     /**
     * @api {get} /comment GetCommentFirstLoadList
     * @apiVersion 0.2.0
     * @apiName GetCommentFirstLoadList
     * @apiGroup comment
     * @apiPermission app
     *
     * @apiDescription 获取首次加载的评论列表
     *
     * @apiParam {Number} app_id *应用id.
     * @apiParam {String} object *实体名称.
     * @apiParam {Number} object_id *实体id.
     * @apiParam {Number} user_id 用户id.
     *
     * @apiSuccess {Boolean} error 是否错误.
     * @apiSuccess {Object[]} result.hot 评论数据.
     * @apiSuccess {String} result.hot.content 评论内容.
     * @apiSuccess {Number} result.hot.star_count 赞数.
     * @apiSuccess {Datetime} result.hot.created_at 创建时间.
     * @apiSuccess {String} result.hot.user_name 用户姓名.
     * @apiSuccess {String} result.hot.user_icon 用户头像.
     * @apiSuccess {String} result.hot.replied_user_name 被回复者姓名.
     * @apiSuccess {Object[]} result.new 评论数据.
     * @apiSuccess {String} result.new.content 评论内容.
     * @apiSuccess {Number} result.new.star_count 赞数.
     * @apiSuccess {Datetime} result.new.created_at 创建时间.
     * @apiSuccess {String} result.new.user_name 用户姓名.
     * @apiSuccess {String} result.new.user_icon 用户头像.
     * @apiSuccess {String} result.new.replied_user_name 被回复者姓名.
     * @apiSuccess {String} message 提示消息
     *
     * @apiError statusError 状态错误.
     * @apiSampleRequest http://dev.timepicker.cn/api/comment/firstload
     */
    function FirstLoadIndex(Request $request){
        $input = $request->all();
        //参数检验
        $validator = Validator::make($input,
            [
                'app_id'      => 'required|integer|min:1',
                'object'      => 'required|string|min:2',
                'object_id'   => 'required|string|min:1',
                'order'       => 'string|min:1',
                'page'        => 'integer|min:1',
                'user_id'     => 'integer'
            ]
        );
        if($validator->fails())
            return $this::jsonResponse(true,$validator->messages(),"paramError");
        
        $commentData = [
            "app_id"   =>$input["app_id"],
            "object"   =>$input["object"],
            "object_id"=>$input["object_id"],
            "order"    =>"hot",
            "user_id"  =>empty($input["user_id"])?0:$input["user_id"]
        ];
        $commentHotResult = $this->indexInner($input);
        
        $commentData = [
            "app_id"   =>$input["app_id"],
            "object"   =>$input["object"],
            "object_id"=>$input["object_id"],
            "order"    =>"new",
            "user_id"  =>empty($input["user_id"])?0:$input["user_id"]
        ];
        $commentNewResult = $this->indexInner($input);
        return $this::jsonResponse(false,["hot"=>$commentHotResult,"new"=>$commentNewResult]);

    }
}